package utils;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

/**
 * Gestionnaire de fichiers de reviews
 * 
 */
public class ReviewFileParser {

	/**
	 * Retourne les reviews d'entrainement d'un dossier
	 * 
	 * @param chemin
	 *            Le chemin du dossier où se trouvent les fichiers de reviews
	 * @param categorie
	 *            Le domaine à utiliser
	 * @return Une ArrayList contenant les reviews
	 * @throws IOException
	 *             Si le fichier d'entrainement n'existe pas dans cette
	 *             catégorie ou dans le dossier passé en paramètre
	 * @throws IndexOutOfBoundsException
	 *             Si la catégorie n'existe pas
	 */
	public ArrayList<Review> getTrainingReviews(String chemin,
			Category categorie) throws IOException, IndexOutOfBoundsException {
		return parseFile(chemin, categorie, "training.txt");
	}

	/**
	 * Retourne les reviews de développement d'un dossier
	 * 
	 * @param chemin
	 *            Le chemin du dossier où se trouvent les fichiers de reviews
	 * @param categorie
	 *            Le domaine à utiliser
	 * @return Une ArrayList contenant les reviews
	 * @throws IOException
	 *             Si le fichier de développement n'existe pas dans cette
	 *             catégorie ou dans le dossier passé en paramètre
	 * @throws IndexOutOfBoundsException
	 *             Si la catégorie n'existe pas
	 */
	public ArrayList<Review> getDevReviews(String chemin, Category categorie)
			throws IOException, IndexOutOfBoundsException {
		return parseFile(chemin, categorie, "dev.txt");
	}
	
	/**
	 * Retourne les reviews de test d'un dossier
	 * 
	 * @param chemin
	 *            Le chemin du dossier où se trouvent les fichiers de reviews
	 * @param categorie
	 *            Le domaine à utiliser
	 * @return Une ArrayList contenant les reviews
	 * @throws IOException
	 *             Si le fichier de test n'existe pas dans cette
	 *             catégorie ou dans le dossier passé en paramètre
	 * @throws IndexOutOfBoundsException
	 *             Si la catégorie n'existe pas
	 */
	public ArrayList<Review> getTestReviews(String chemin, Category categorie)
			throws IOException, IndexOutOfBoundsException {
		return parseFile(chemin, categorie, "test.txt");
	}

	/**
	 * Retourne les reviews sans étiquette d'un dossier
	 * 
	 * @param chemin
	 *            Le chemin du dossier où se trouvent les fichiers de reviews
	 * @param categorie
	 *            Le domaine à utiliser
	 * @return Une ArrayList contenant les reviews
	 * @throws IOException
	 *             Si le fichier sans étiquettes n'existe pas dans cette
	 *             catégorie ou dans le dossier passé en paramètre
	 * @throws IndexOutOfBoundsException
	 *             Si la catégorie n'existe pas
	 */
	public ArrayList<Review> getUnlabReviews(String chemin, Category categorie)
			throws IOException, IndexOutOfBoundsException {
		return parseFile(chemin, categorie, "unlab.txt");
	}

	/**
	 * Lit un fichier et en fait une ArrayList de Review
	 * 
	 * @param path
	 *            Le chemin du dossier contenant toutes les reviews
	 * @param categorie
	 *            Le domaine de travail
	 * @param fichier
	 *            Le nom du fichier à ouvrir
	 * @return Une ArrayList de Review représentant les reviews du fichier
	 * @throws IOException
	 *             Si le fichier n'existe pas
	 * @throws IndexOutOfBoundsException
	 *             Si le domaine est incorrect
	 */
	private ArrayList<Review> parseFile(String path, Category categorie,
			String fichier) throws IOException, IndexOutOfBoundsException {
		String filePath = "";
		String dossier = "";
		String ligne;
		int id = -1;
		Opinion opinion = null;
		String texte = "";
		String tmp;
		ArrayList<Review> liste = new ArrayList<Review>();

		switch (categorie) {
		case DVD:
			dossier = "dvd";
			break;
		case ELECTRONICS:
			dossier = "electronics";
			break;
		case KITCHEN:
			dossier = "kitchen";
			break;
		case BOOKS:
			dossier = "books";
			break;
		default:
			throw new IndexOutOfBoundsException("Erreur de choix de catégorie.");
		}
		if (!path.endsWith(System.getProperty("file.separator"))) {
			path += System.getProperty("file.separator");
		}
		filePath = path + dossier + System.getProperty("file.separator")
				+ fichier;

		InputStream input = new FileInputStream(filePath);
		InputStreamReader inputReader = new InputStreamReader(input);
		BufferedReader buffered = new BufferedReader(inputReader);
		while ((ligne = buffered.readLine()) != null) {
			// A la fin d'une review
			if (ligne.startsWith("</review")) {
				// On enregistre la pr�c�dente
				liste.add(new Review(id, opinion, texte));
				// On efface tout
				id = -1;
				opinion = null;
				tmp = "";
				texte = "";
			}
			// Au début d'une review
			else if (ligne.startsWith("<review")) {
				// On récupère l'id
				tmp = ligne.substring(ligne.indexOf("id=") + 4);
				tmp = tmp.substring(0, tmp.indexOf("\'"));
				try {
					id = Integer.parseInt(tmp);
				} catch (NumberFormatException nfe) {
					nfe.printStackTrace();
					id = -1;
				}

				// On récupère l'opinion
				tmp = ligne.substring(ligne.indexOf("class=") + 7);
				tmp = tmp.substring(0, tmp.indexOf("\'"));
				if (tmp.equals("positive")) {
					opinion = Opinion.POSITIVE;
				} else if (tmp.equals("negative")) {
					opinion = Opinion.NEGATIVE;
				} else {
					opinion = Opinion.UNKNOWN;
				}
			}
			// Au milieu d'une review
			else if (ligne != "") {
				texte += " " + ligne;
			}
		}
		buffered.close();
		return liste;
	}
}
